package com.yangl.corejava.util;

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Base64Util {
    private static final Class<?> cls1;
    private static final Constructor<?> cons1;
    private static final Object obj1;
    private static final Method encodeMethod;
    private static final Class<?> cls2;
    private static final Constructor<?> cons2;
    private static final Object obj2;
    private static final Method decodeMethod;
    private static final ThreadLocal<Object> ENCODER_SUPPLIER = new ThreadLocal();
    private static final ThreadLocal<Object> DECODER_SUPPLIER = new ThreadLocal();

    public Base64Util() {
    }

    public static String getBASE64(byte[] bytes) {
        if (bytes == null) {
            return null;
        } else {
            try {
                Object encoder = obj1;
                if (encodeMethod.getName().equals("encode")) {
                    encoder = ENCODER_SUPPLIER.get();
                    if (encoder == null) {
                        ENCODER_SUPPLIER.set(cons1.newInstance());
                    }
                }

                Object res = encodeMethod.invoke(obj1, bytes);
                return String.valueOf(res);
            } catch (Exception var3) {
                throw new RuntimeException(var3);
            }
        }
    }

    public static String getBASE64FromFile(String fileName) throws IOException {
        if (fileName == null) {
            return null;
        } else {
            FileInputStream input = null;

            String var3;
            try {
                input = new FileInputStream(fileName);
                byte[] bytes = new byte[input.available()];
                input.read(bytes);
                var3 = getBASE64(bytes);
            } catch (IOException var7) {
                throw var7;
            } finally {
                if (input != null) {
                    input.close();
                }

            }

            return var3;
        }
    }

    public static byte[] getBytesFromBASE64(String s) {
        if (s == null) {
            return null;
        } else {
            try {
                Object decoder = obj2;
                if (decodeMethod.getName().equals("decodeBuffer")) {
                    decoder = DECODER_SUPPLIER.get();
                    if (decoder == null) {
                        DECODER_SUPPLIER.set(decoder = cons2.newInstance());
                    }
                }

                return (byte[])((byte[])decodeMethod.invoke(decoder, s));
            } catch (Exception var2) {
                throw new RuntimeException(var2);
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(4);

        while(true) {
            pool.execute(new Runnable() {
                public void run() {
                    String content = "just for test!";
                    String retStr = new String(Base64Util.getBytesFromBASE64(Base64Util.getBASE64(content.getBytes())));
                    if (!content.equals(retStr)) {
                        System.out.println("?????:" + retStr);
                    } else {
                        System.out.print("-");
                    }

                }
            });
        }
    }

    static {
        String javaVersion = System.getProperty("java.version");
        if (!javaVersion.startsWith("1.")) {
            try {
                cls1 = Class.forName("java.util.Base64$Encoder");
                cons1 = cls1.getDeclaredConstructor(Boolean.TYPE, byte[].class, Integer.TYPE, Boolean.TYPE);
                cons1.setAccessible(true);
                obj1 = cons1.newInstance(false, null, -1, true);
                encodeMethod = cls1.getMethod("encodeToString", byte[].class);
                cls2 = Class.forName("java.util.Base64$Decoder");
                cons2 = cls2.getDeclaredConstructor(Boolean.TYPE, Boolean.TYPE);
                cons2.setAccessible(true);
                obj2 = cons2.newInstance(false, false);
                decodeMethod = cls2.getMethod("decode", String.class);
            } catch (Throwable var3) {
                throw new RuntimeException(var3);
            }
        } else {
            try {
                cls1 = Class.forName("sun.misc.BASE64Encoder");
                cons1 = cls1.getConstructor();
                obj1 = cons1.newInstance();
                encodeMethod = cls1.getMethod("encode", byte[].class);
                cls2 = Class.forName("sun.misc.BASE64Decoder");
                cons2 = cls2.getConstructor();
                obj2 = cons2.newInstance();
                decodeMethod = cls2.getMethod("decodeBuffer", String.class);
            } catch (Throwable var2) {
                throw new RuntimeException(var2);
            }
        }

    }
}
